/**
 * Apr 3, 2010
 */
package org.tomale.id.gis.ui;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.media.opengl.GL;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.glu.GLU;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.opengl.GLData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.EditorPart;
import org.tomale.id.gis.Activator;
import org.tomale.id.gis.ILayerProvider;
import org.tomale.id.gis.IRenderer;
import org.tomale.id.gis.preferences.PreferenceConstants;
import org.tomale.id.gis.ui.internal.MapCanvas;

/**
 * @author ferd
 *
 */
public class MapEditor extends EditorPart {

	public final static String EDITOR_ID = "org.tomale.id.gis.ui.mapeditor";
	
//	MapCanvas _canvas;
	GLCanvas _canvas;
	GLContext _context;
	
	private float _rotateX;
	private float _rotateY;
	private float _rotateZ;
	private float _rotateIncrement = 0.05f;
	
	private float _offsetX;
	private float _offsetY;
	private float _offsetZ;
	private float _panIncrement = 0.05f;
	
	private boolean _dirty = false;

	private HashMap<String, IRenderer> _renderers = new HashMap<String, IRenderer>();
	private List<ILayerProvider> _layers = new ArrayList<ILayerProvider>();
	
	public MapEditor(){
		
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	public void doSave(IProgressMonitor monitor) {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.EditorPart#doSaveAs()
	 */
	@Override
	public void doSaveAs() {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.EditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
	 */
	@Override
	public void init(IEditorSite site, IEditorInput input)
			throws PartInitException {
		setSite(site);
		setInput(input);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.EditorPart#isDirty()
	 */
	@Override
	public boolean isDirty() {
		return _dirty;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
	 */
	@Override
	public boolean isSaveAsAllowed() {
		// TODO Auto-generated method stub
		return false;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
	 */
	@Override
	public void createPartControl(Composite parent) {
		setPreferences();
		
		GLData data = new GLData();
		data.doubleBuffer = true;
		_canvas = new MapCanvas(parent, SWT.NONE, data);
		_canvas.setCurrent();
		
		_context = GLDrawableFactory.getFactory().createExternalGLContext();
		_context.makeCurrent();
		GL gl = _context.getGL();
		
		gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
		gl.glColor3f(1.0f, 0.0f, 0.0f);
		gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
		gl.glClearDepth(1.0);
		gl.glLineWidth(2);
		gl.glEnable(GL.GL_DEPTH_TEST);
		
		_context.release();
		
		_canvas.addControlListener(new ControlListener() {
			
			@Override
			public void controlResized(ControlEvent e) {
				resize();
			}
			
			@Override
			public void controlMoved(ControlEvent e) {
				
			}
		});
		
		_canvas.addKeyListener(new KeyListener() {
			
			@Override
			public void keyReleased(KeyEvent e) {
				switch(e.keyCode){
					case SWT.ARROW_UP:{
						if((e.stateMask & SWT.CTRL)!=0){
							_rotateY += _rotateIncrement;
						} else {
							_offsetY -= _panIncrement;
						}
						break;
					}
					case SWT.ARROW_DOWN:{
						if((e.stateMask & SWT.CTRL)!=0){
							_rotateY -= _rotateIncrement;
						} else {
							_offsetY += _panIncrement;
						}
						break;
					}
					case SWT.ARROW_LEFT:{
						if((e.stateMask & SWT.CTRL)!=0){
							_rotateZ -= _rotateIncrement;
						} else {
							_offsetX += _panIncrement;
						}
						break;
					}
					case SWT.ARROW_RIGHT:{
						if((e.stateMask & SWT.CTRL)!=0){
							_rotateZ += _rotateIncrement;
						} else {
							_offsetX -= _panIncrement;
						}
					}
				}
			}
			
			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub
				
			}
		});
		
		_canvas.getDisplay().asyncExec(new Runnable() {
			
			@Override
			public void run() {
				paint();
				if(!_canvas.isDisposed()){
					_canvas.getDisplay().asyncExec(this);
				}
			}
		});
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
	 */
	@Override
	public void setFocus() {
		_canvas.setFocus();
	}
	
	private void resize(){
		Rectangle rect = _canvas.getBounds();
		float aspect = rect.width / rect.height;
		_canvas.setCurrent();
		_context.makeCurrent();
		
		GL gl = _context.getGL();
		
		gl.glViewport(0, 0, rect.width, rect.height);
		gl.glMatrixMode(GL.GL_PROJECTION);
		gl.glLoadIdentity();
		GLU glu = new GLU();
		glu.gluPerspective(45.0f, aspect, 0.5f, 400.0f);
		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLoadIdentity();
		
		_context.release();
	}
	
	private void paint(){
		if(!_canvas.isDisposed()){
			_canvas.setCurrent();
			_context.makeCurrent();
			
			GL gl = _context.getGL();
	
			gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
			gl.glLoadIdentity();
		    
			gl.glTranslatef(this._offsetX, this._offsetY, -6.0f);
			gl.glRotatef(this._rotateZ, 0.0f, 0.0f, 1.0f);
		    
		    gl.glBegin(GL.GL_QUADS);
		    gl.glVertex3f(-1.0f, 1.0f, 0.0f);
		    gl.glVertex3f(1.0f, 1.0f, 0.0f);
		    gl.glVertex3f(1.0f, -1.0f, 0.0f);
		    gl.glVertex3f(-1.0f, -1.0f, 0.0f);
		    gl.glEnd();
		    
			_canvas.swapBuffers();
			_context.release();
		}
	}
	
	private void setPreferences(){
		IPreferenceStore store = Activator.getDefault().getPreferenceStore();
		_rotateIncrement = store.getFloat(PreferenceConstants.ROTATE_INCREMENT);
		if(_rotateIncrement<PreferenceConstants.DEFAULT_ROTATE_INCREMENT){
			_rotateIncrement = PreferenceConstants.DEFAULT_ROTATE_INCREMENT;
		}
		_panIncrement = store.getFloat(PreferenceConstants.PAN_INCREMENT);
		if(_panIncrement<PreferenceConstants.DEFAULT_PAN_INCREMENT){
			_panIncrement = PreferenceConstants.DEFAULT_PAN_INCREMENT;
		}
	}
	
	private void getElements(){
		
	}
	
	private void initRenderers(){
		
	}
}
